/*
 * AbstractGenerator.cc
 *
 *  Created on: 2011-03-04
 *      Author: Jagger
 */

#include "AbstractGenerator.h"

int AbstractGenerator::totalNumGenerated = 0;

void AbstractGenerator::initialize()
{
	numGenerated = 0;
	WATCH(numGenerated);

	intervalEvent = new cMessage("intervalEvent");
	intervalSignal = registerSignal("interval");

	startTime 	= par("startTime");
	endTime		= par("endTime");
	tick		= par("tick");

	simtime_t arrivalTime = getNextPacketArrivalTime(startTime);
	emit(intervalSignal, arrivalTime - startTime);

	scheduleAt(arrivalTime, intervalEvent);
}

void AbstractGenerator::handleMessage(cMessage* msg)
{
	simtime_t currentTime = simTime();

	if(msg == intervalEvent && canGenerate(currentTime))
	{
		// Uwzgledniamy opoznienie wynikajace z niedoskonalosci kanalu wyjsciowego
		cGate* out = gate("out");
		cChannel* channel = out->getChannel();
		if(channel)
		{
			simtime_t finishTime = channel->getTransmissionFinishTime();
			simtime_t delay = std::max(finishTime - currentTime, SIMTIME_ZERO);
			sendDelayed(createPacket(), delay, out);
		}
		else
			send(createPacket(), out);

		simtime_t arrivalTime = getNextPacketArrivalTime(currentTime);
		emit(intervalSignal, arrivalTime - currentTime);

		scheduleAt(arrivalTime, intervalEvent);
	}
	else
		delete msg;
}

NetPacket* AbstractGenerator::createPacket()
{
	char packetName[32];

	totalNumGenerated++;
	numGenerated++;
	sprintf(packetName, "pck-%d", totalNumGenerated);

	NetPacket* packet = new NetPacket(packetName);

	int32_t srcId	 = getId();
	int32_t payload  = par("payloadLength");
	int32_t priority = par("packetPriority");

	packet->setPacketId(totalNumGenerated);
	packet->setSrc(srcId);
	packet->setByteLength(payload);
	packet->setPriority(priority);
	packet->setMakeTime(simTime());

	EV << "Generated packet. Id: " << totalNumGenerated << " Payload: " << payload << " Priority: " << priority << "\n";

	return packet;
}

bool AbstractGenerator::canGenerate(simtime_t time) const
{
	return time < endTime || endTime == 0;
}
